// A Map is a collection of tiles.
//
// The easiest way to store the places is an 2D array.
//
// A Map is a way to access the 2D internal array in an easiest way.

package com.fduss.mazegame.core.maze;

import com.fduss.mazegame.core.unit.Place;
import com.fduss.mazegame.core.unit.feature.Icon;
import com.fduss.mazegame.util.Array;
import com.fduss.mazegame.util.OpaqueSack;
import com.fduss.mazegame.util.OpaqueSackArray;

public class Map {

    private Place[][] places;

    public Map(Place[][] places) {
        if (places == null) {
            throw new NullPointerException("places");
        }
        if (Array.hasNull(places)) {
            throw new NullPointerException("maze places has nulls");
        }
        if (!Array.isRect(places)) {
            throw new IllegalArgumentException(
                    "maze is not rectangular");
        }
        this.places = places;
        for (int i = 0; i < places.length; i++) {
            for (int j = 0; j < places[i].length; j++) {
                places[i][j].setPlace(i, j);
                places[i][j].setMap(this);
            }
        }
    }

    public int getNumRows() {
        return places.length;
    }

    public int getNumCols() {
        return places[0].length;
    }

    public Place getPlace(int r, int c) {
        if (r < 0) {
            throw new IllegalArgumentException("r < 0");
        }
        if (r > getNumRows()) {
            throw new IllegalArgumentException(
                    "r > number of rows in the maze");
        }
        if (c < 0) {
            throw new IllegalArgumentException("c < 0");
        }
        if (c > getNumCols()) {
            throw new IllegalArgumentException(
                    "c > number of columns in the maze");
        }
        return places[r][c];
    }

    public Icon[][] getIcons() {
        Icon[][] icons = new Icon[getNumRows()][getNumCols()];
        for (int r = 0; r < getNumRows(); r++) {
            for (int c = 0; c < getNumCols(); c++) {
                Place p = places[r][c];
                int num = p.getEntiesNum();
                if (num <= 0)
                    icons[r][c] = p.getIcon();
                else
                    icons[r][c] = p.getEntity(num - 1).getIcon();
            }
        }
        return icons;
    }

    public OpaqueSack<Place> getWalkables() {
        int rows = places.length;
        int cols = places[0].length;
        OpaqueSack<Place> list = new OpaqueSackArray<>();
        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                if (places[r][c].isWalkable()) {
                    list.add(getPlace(r, c));
                }
            }
        }
        return list;
    }
}
